package com.lvcoding.auth2.auth.custom.grant;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.Assert;

/**
 * 自定义认证提供者
 *
 * @author wuyanshen
 */
@Slf4j
public class CustomAuthenticationProvider implements AuthenticationProvider {


    private PasswordEncoder passwordEncoder;

    private UserDetailsService userDetailsService;


    public CustomAuthenticationProvider() {
        setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
    }

    protected void additionalAuthenticationChecks(CustomAuthenticationToken authentication) throws AuthenticationException {
        if (authentication.getCredentials() == null) {
            log.debug("Failed to authenticate since no credentials provided");
            throw new BadCredentialsException("Bad credentials");
        }
        String code = authentication.getCredentials().toString();
        // TODO 校验短信验证码正确性
        log.info("短信验证码是：" + code);
    }


    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        CustomAuthenticationToken requestToken = (CustomAuthenticationToken) authentication;

        // 认证类型
        String grantType = requestToken.getGrantType();

        // 此处已获得 客户端认证 获取对应 userDetailsService
        Authentication clientAuthentication = SecurityContextHolder.getContext().getAuthentication();
        String clientId = clientAuthentication.getName();

        CustomAuthenticationToken customAuthenticationToken = new CustomAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), AuthorityUtils.createAuthorityList("cup:user:view"));

        // 校验验证码是否正确
        additionalAuthenticationChecks(customAuthenticationToken);

        customAuthenticationToken.setDetails(authentication.getDetails());
        return customAuthenticationToken;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.isAssignableFrom(CustomAuthenticationToken.class);
    }


    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        Assert.notNull(passwordEncoder, "passwordEncoder cannot be null");
        this.passwordEncoder = passwordEncoder;
    }

    protected PasswordEncoder getPasswordEncoder() {
        return this.passwordEncoder;
    }

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    protected UserDetailsService getUserDetailsService() {
        return this.userDetailsService;
    }

}
